#include "A_Config.h"

const char *charge_current = "100 mA\n190 mA\n280 mA\n360 mA\n450 mA\n550 mA\n630 mA\n700 mA\n780 mA\n880 mA\n960 mA\n1000 mA\n1080 mA\n1160 mA\n1240 mA\n1320 mA";

static lv_obj_t *tab_settings;
static bool btnSyncClock = false;
static bool btnOffsetClock = false;

static bool btnResetCoulomb = false;

static bool btnSaveAndReboot = false;
static bool btnDontSaveAndReboot = false;
static bool btnExit = false;
static bool btnOTA = false;
static bool btnCali = false;
static bool btnAbout = false;
///////////////////////////////////设置项列表//////////////////////////////////////////////////////////
static bool settings_isMute = false;                             // 是否静音
static int32_t settings_volume = CONFIG_DEFAULT_VOLUME;          // 音量调节
static int32_t settings_brightness = CONFIG_DEFAULT_BRIGHTNESS;  // 音量调节
static int32_t settings_autoSleepTime = AUTO_SLEEP_TIME_DEFAULT; // 亮度调节
static bool settings_notifyAtClass = false;                      // 上课提醒设置
static bool settings_notifyAtClassOver = false;                  // 下课提醒设置
static bool settings_updateWeatherDaily = false;                 // 每日更新天气
static int32_t settings_printerDensity = 40;                     // 打印颜色深度
static uint16_t settings_batteryChargeCurrent = 7;
static bool settings_enableCoulomb = false;
//////////////////////////////////////////////////////////////////////////////////////////////////////

class AppSettings : public AppBase
{
private:
    /* data */
public:
    AppSettings()
    {
        name = "settings";
        title = "设置";
        description = "";
        image = "\xEF\x80\x93";
    }
    void setup();
    void loop();
    void destruct();
};

static void switch_event_cb(lv_event_t *e)
{
    lv_obj_t *obj = lv_event_get_target(e);
    bool *checked = (bool *)lv_event_get_user_data(e);
    *checked = lv_obj_has_state(obj, LV_STATE_CHECKED);
}
lv_obj_t *settings_add_switch(lv_obj_t *parent, const char *title, const char *help, bool *checked)
{
    lv_obj_t *obj = lv_obj_create(parent);
    lv_obj_set_size(obj, screenWidth - 20, 80);
    lv_obj_set_style_pad_all(obj, 6, 0);
    lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_t *obj1 = lv_obj_create(obj);
    lv_obj_set_size(obj1, 220, 68);
    lv_obj_set_style_pad_all(obj1, 0, 0);
    lv_obj_set_style_border_width(obj1, 0, 0);
    lv_obj_set_style_clip_corner(obj1, 0, 0);

    lv_obj_t *label = lv_label_create(obj1);
    lv_label_set_text(label, title);
    lv_obj_set_style_text_font(label, &lv_font_chinese_16, 0);
    lv_obj_set_width(label, lv_pct(100));
    lv_obj_set_pos(label, 0, 0);
    label = lv_label_create(obj1);
    lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP);
    lv_obj_set_width(label, lv_pct(100));
    lv_obj_set_height(label, 36);
    lv_obj_set_style_text_font(label, &lv_font_chinese_16, 0);
    lv_label_set_text(label, help);
    lv_obj_set_pos(label, 0, 18);
    lv_obj_set_style_text_color(label, lv_palette_main(LV_PALETTE_GREY), 0);

    lv_obj_t *sw = lv_switch_create(obj);
    lv_obj_align(sw, LV_ALIGN_RIGHT_MID, 0, 0);
    if (*checked)
        lv_obj_add_state(sw, LV_STATE_CHECKED);
    else
        lv_obj_clear_state(sw, LV_STATE_CHECKED);

    lv_obj_add_event_cb(sw, switch_event_cb, LV_EVENT_CLICKED, checked);
    lv_obj_set_user_data(obj, sw);
    return obj;
}

static void slider_event_cb(lv_event_t *e)
{
    lv_obj_t *slider = lv_event_get_target(e);
    int32_t *value_to = (int32_t *)lv_obj_get_user_data(slider);
    *value_to = lv_slider_get_value(slider);
    char buf[8];
    lv_snprintf(buf, sizeof(buf), "%d", *value_to);
    lv_label_set_text((lv_obj_t *)lv_event_get_user_data(e), buf);
}
lv_obj_t *settings_add_slider(lv_obj_t *parent, const char *title, const char *help, int32_t min, int32_t max, int32_t *value_set_to, lv_event_cb_t cb)
{
    lv_obj_t *obj = lv_obj_create(parent);
    lv_obj_set_size(obj, screenWidth - 20, 100);
    lv_obj_set_style_pad_all(obj, 6, 0);
    lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_t *obj1 = lv_obj_create(obj);
    lv_obj_set_size(obj1, lv_pct(100), 68);
    lv_obj_set_align(obj1, LV_ALIGN_TOP_MID);
    lv_obj_set_style_pad_all(obj1, 0, 0);
    lv_obj_set_style_border_width(obj1, 0, 0);
    lv_obj_set_style_clip_corner(obj1, 0, 0);

    lv_obj_t *label = lv_label_create(obj1);
    lv_label_set_text(label, title);
    lv_obj_set_style_text_font(label, &lv_font_chinese_16, 0);
    lv_obj_set_width(label, lv_pct(100));
    lv_obj_set_pos(label, 0, 0);

    label = lv_label_create(obj1);
    lv_obj_set_width(label, lv_pct(100));
    lv_obj_set_height(label, 36);
    lv_obj_set_style_text_font(label, &lv_font_chinese_16, 0);
    lv_label_set_text(label, help);
    lv_obj_set_pos(label, 0, 18);
    lv_obj_set_style_text_color(label, lv_palette_main(LV_PALETTE_GREY), 0);

    lv_obj_t *slider = lv_slider_create(obj);
    lv_obj_set_align(slider, LV_ALIGN_BOTTOM_MID);
    lv_slider_set_range(slider, min, max);
    lv_slider_set_value(slider, *value_set_to, LV_ANIM_OFF);

    lv_obj_t *slider_label = lv_label_create(obj);
    lv_label_set_text(slider_label, String(*value_set_to).c_str());
    lv_obj_align_to(slider_label, slider, LV_ALIGN_OUT_TOP_MID, 0, -5);

    lv_obj_add_event_cb(slider, slider_event_cb, LV_EVENT_VALUE_CHANGED, slider_label);
    lv_obj_set_user_data(slider, value_set_to);
    if (cb)
        lv_obj_add_event_cb(slider, cb, LV_EVENT_VALUE_CHANGED, NULL);

    lv_obj_set_user_data(obj, slider);
    return obj;
}

static void button_event_cb(lv_event_t *e)
{
    bool *pressed = (bool *)lv_event_get_user_data(e);
    *pressed = true;
}
lv_obj_t *settings_add_button(lv_obj_t *parent, const char *title, const char *help, const char *btnText, bool *pressed)
{
    lv_obj_t *obj = lv_obj_create(parent);
    lv_obj_set_size(obj, screenWidth - 20, 80);
    lv_obj_set_style_pad_all(obj, 6, 0);
    lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_t *obj1 = lv_obj_create(obj);
    lv_obj_set_size(obj1, 220, 68);
    lv_obj_set_style_pad_all(obj1, 0, 0);
    lv_obj_set_style_border_width(obj1, 0, 0);
    lv_obj_set_style_clip_corner(obj1, 0, 0);

    lv_obj_t *label = lv_label_create(obj1);
    lv_label_set_text(label, title);
    lv_obj_set_style_text_font(label, &lv_font_chinese_16, 0);
    lv_obj_set_width(label, lv_pct(100));
    lv_obj_set_pos(label, 0, 0);
    label = lv_label_create(obj1);
    lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP);
    lv_obj_set_width(label, lv_pct(100));
    lv_obj_set_height(label, 36);
    lv_obj_set_style_text_font(label, &lv_font_chinese_16, 0);
    lv_label_set_text(label, help);
    lv_obj_set_pos(label, 0, 18);
    lv_obj_set_style_text_color(label, lv_palette_main(LV_PALETTE_GREY), 0);

    lv_obj_t *button = lv_btn_create(obj);
    lv_obj_align(button, LV_ALIGN_RIGHT_MID, 0, 0);
    label = lv_label_create(button);
    lv_obj_set_style_text_font(label, &lv_font_chinese_16, 0);
    lv_label_set_text(label, btnText);
    lv_obj_center(label);
    *pressed = false;
    lv_obj_add_event_cb(button, button_event_cb, LV_EVENT_CLICKED, pressed);
    lv_obj_set_user_data(obj, NULL);
    return obj;
}

static void roller_event_handler(lv_event_t *e)
{
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t *obj = lv_event_get_target(e);
    uint16_t *chosen = (uint16_t *)lv_event_get_user_data(e);
    *chosen = lv_roller_get_selected(obj);
}

lv_obj_t *settings_add_roller(lv_obj_t *parent, const char *title, const char *help, const char *options, uint16_t *chosen)
{
    lv_obj_t *obj = lv_obj_create(parent);
    lv_obj_set_size(obj, screenWidth - 20, 120);
    lv_obj_set_style_pad_all(obj, 6, 0);
    lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_t *obj1 = lv_obj_create(obj);
    lv_obj_set_size(obj1, 180, 120 - 12);
    lv_obj_set_style_pad_all(obj1, 0, 0);
    lv_obj_set_style_border_width(obj1, 0, 0);
    lv_obj_set_style_clip_corner(obj1, 0, 0);

    lv_obj_t *label = lv_label_create(obj1);
    lv_label_set_text(label, title);
    lv_obj_set_style_text_font(label, &lv_font_chinese_16, 0);
    lv_obj_set_width(label, lv_pct(100));
    lv_obj_set_pos(label, 0, 0);
    label = lv_label_create(obj1);
    lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP);
    lv_obj_set_width(label, lv_pct(100));
    lv_obj_set_height(label, 36);
    lv_obj_set_style_text_font(label, &lv_font_chinese_16, 0);
    lv_label_set_text(label, help);
    lv_obj_set_pos(label, 0, 18);
    lv_obj_set_style_text_color(label, lv_palette_main(LV_PALETTE_GREY), 0);

    lv_obj_t *roller1 = lv_roller_create(obj);
    lv_obj_set_width(roller1, screenWidth - 20 - 180 - 10);
    lv_obj_set_height(roller1, lv_pct(100));
    lv_obj_align(roller1, LV_ALIGN_RIGHT_MID, 0, 0);
    lv_roller_set_options(roller1, options, LV_ROLLER_MODE_INFINITE);
    lv_roller_set_selected(roller1, *chosen, LV_ANIM_OFF);
    lv_obj_add_event_cb(roller1, roller_event_handler, LV_EVENT_VALUE_CHANGED, chosen);
    lv_obj_set_user_data(obj, roller1);
    return obj;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void event_brightness_cb(lv_event_t *e)
{
    hal.setBrightness(settings_brightness);
}

void saveSettings()
{
    if (settings_autoSleepTime < 5000)
        settings_autoSleepTime = 5000;
    settings.setBool("settings.ismute", settings_isMute);
    settings.setBool("settings.nclass", settings_notifyAtClass);
    settings.setBool("settings.nclassov", settings_notifyAtClassOver);
    settings.setBool("settings.upweather", settings_updateWeatherDaily);
    settings.setInt("settings.volume", settings_volume);
    settings.setInt("settings.brightness", settings_brightness);
    settings.setInt("settings.printdensity", settings_printerDensity);
    settings.setInt("settings.chargecurrent", settings_batteryChargeCurrent);
    settings.setInt("settings.autosleep", settings_autoSleepTime);
    settings.setBool("settings.encoulomb", settings_enableCoulomb);
    settings.writeSettings(CONFIG_FILE_NAME);
    Serial.println("Saved! " CONFIG_FILE_NAME);
    JsonObject ob = settings.getRoot();
    if (!ob.isNull())
    {
        serializeJsonPretty(ob, Serial);
        Serial.println("");
    }
    hal.autoSleepTime = settings_autoSleepTime;
}
void AppSettings::setup()
{
    settings_isMute = settings.getBool("settings.ismute", settings_isMute);
    settings_notifyAtClass = settings.getBool("settings.nclass", settings_notifyAtClass);
    settings_notifyAtClassOver = settings.getBool("settings.nclassov", settings_notifyAtClassOver);
    settings_updateWeatherDaily = settings.getBool("settings.upweather", settings_updateWeatherDaily);
    settings_enableCoulomb = settings.getBool("settings.encoulomb", settings_enableCoulomb);
    settings_volume = settings.getInt("settings.volume", settings_volume);
    settings_brightness = settings.getInt("settings.brightness", settings_brightness);
    settings_printerDensity = settings.getInt("settings.printdensity", settings_printerDensity);
    settings_batteryChargeCurrent = settings.getInt("settings.chargecurrent", settings_batteryChargeCurrent);
    settings_autoSleepTime = settings.getInt("settings.autosleep", settings_autoSleepTime);

    LOCKLV();
    tab_settings = lv_tabview_create(scr, LV_DIR_TOP, 40);
    lv_obj_set_style_text_font(tab_settings, &lv_font_chinese_16, 0);
    lv_obj_fade_in(tab_settings, 300, 0);
    /*Add 3 tabs (the tabs are page (lv_page) and can be scrolled*/
    lv_obj_t *tab1 = lv_tabview_add_tab(tab_settings, "时间设置");
    lv_obj_t *tab2 = lv_tabview_add_tab(tab_settings, "系统设置");
    lv_obj_t *tab3 = lv_tabview_add_tab(tab_settings, "保存");

    lv_obj_set_flex_flow(tab1, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_style_pad_all(tab1, 8, 0);
    lv_obj_set_flex_flow(tab2, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_style_pad_all(tab2, 8, 0);
    lv_obj_set_flex_flow(tab3, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_style_pad_all(tab3, 8, 0);

    ////////////////TAB-1//////////////////
    settings_add_button(tab1, "同步网络时间", "通过NTP服务器同步网络时间，需要连接WiFi", "同步", &btnSyncClock);
    settings_add_switch(tab1, "上课提醒", "是否打开上课提醒功能", &settings_notifyAtClass);
    settings_add_switch(tab1, "下课提醒", "是否打开下课提醒功能", &settings_notifyAtClassOver);
    settings_add_switch(tab1, "每日更新天气", "是否自动与ESPNow网关更新天气", &settings_updateWeatherDaily);
    settings_add_button(tab1, "秒针微调", "手动微调RTC秒针，应对学校\nRTC几天慢一秒的问题", "打开", &btnOffsetClock);
    //////////////END TAB-1////////////////
    ////////////////TAB-2//////////////////
    settings_add_switch(tab2, "静音模式", "设置是否禁用内置蜂鸣器", &settings_isMute);
    settings_add_slider(tab2, "音量调节", "调节音量", 0, 255, &settings_volume, NULL);
    settings_add_slider(tab2, "亮度调节", "调节LCD背光亮度", 1, 100, &settings_brightness, event_brightness_cb);
    settings_add_slider(tab2, "自动休眠", "改变自动休眠时间，单位毫秒", 5000, 30000, &settings_autoSleepTime, NULL);
    settings_add_slider(tab2, "打印深度", "调节打印机加热时间", 20, 60, &settings_printerDensity, NULL);
    settings_add_roller(tab2, "充电电流", "设置电池充电电流，最好不要超过电池容量", charge_current, &settings_batteryChargeCurrent);
    settings_add_switch(tab2, "启用库仑计", "设置是否打开内置库仑计，可能会增加耗电（可能）", &settings_enableCoulomb);
    settings_add_button(tab2, "复位电池库仑计", "复位电池库仑计，请在充满电或完全放电结束后使用", "执行", &btnResetCoulomb);
    //////////////END TAB-2////////////////
    ////////////////TAB-3//////////////////
    settings_add_button(tab3, "保存并重启", "保存并重启ESP32，保证所有设置被正常应用", "保存", &btnSaveAndReboot);
    settings_add_button(tab3, "不保存重启", "直接重启ESP32，舍弃所有更改", "重启", &btnDontSaveAndReboot);
    settings_add_button(tab3, "直接退出", "退出设置，不保存更改，但是已修改的设置会被保留", "退出", &btnExit);
    settings_add_button(tab3, "OTA升级", "进入OTA无线升级模式", "OTA", &btnOTA);
    settings_add_button(tab3, "触摸屏校准", "进行触摸屏校准，如果触摸不准可以使用", "执行", &btnCali);
    settings_add_button(tab3, "关于本机", "", "查看", &btnAbout);

    //////////////END TAB-3////////////////
    UNLOCKLV();
}

void AppSettings::loop()
{

    if (btnSyncClock)
    {
        btnSyncClock = false;
        hal.DoNotSleep = true;
        if (WiFiMgr.autoConnect() == true)
        {
            if (hal.NTPSync())
            {
                char tmp[70];
                sprintf(tmp, "网络时间：20%02d年%02d月%02d日 %02d时%02d分%02d秒", hal.rtc.year, hal.rtc.month, hal.rtc.day, hal.rtc.hour, hal.rtc.minute, hal.rtc.sec);
                full_screen_msgbox(BIG_SYMBOL_CHECK, "同步成功", tmp,
                                   FULL_SCREEN_BG_CHECK, 3000);
            }
            else
            {
                full_screen_msgbox(BIG_SYMBOL_CROSS, "同步失败",
                                   "同步失败，请检查网络连接稳定性", FULL_SCREEN_BG_CROSS, 3000);
            }
        }
        hal.DoNotSleep = false;
    }
    if (btnOffsetClock)
    {
        btnOffsetClock = false;
        // 秒针微调，应对学校rtc几天慢一秒的问题
        int16_t tmp = msgbox_number("偏移秒数", 15, -15, 0);
        lv_obj_t *msgbox_full;
        if (abs(tmp) > 2)
        {
            msgbox_full = full_screen_msgbox_create(BIG_SYMBOL_SYNC,
                                                    "秒钟微调",
                                                    "正在调节",
                                                    FULL_SCREEN_BG_SYNC);
        }
        hal.DoNotSleep = true;
        hal.rtcOffsetSecond(tmp);
        if (abs(tmp) > 2)
        {
            full_screen_msgbox_del(msgbox_full);
        }
        full_screen_msgbox(BIG_SYMBOL_CHECK, "秒针微调", "调节成功", FULL_SCREEN_BG_CHECK, 2000);
        hal.DoNotSleep = false;
    }
    if (btnResetCoulomb)
    {
        btnResetCoulomb = false;
#ifdef CMD_PASSWORD
        if (msgbox_passwd() == CMD_PASSWORD)
        {
#endif
            xSemaphoreTake(hal.wiremutex, portMAX_DELAY);
            hal.axp.ClearCoulombcounter();
            xSemaphoreGive(hal.wiremutex);
#ifdef CMD_PASSWORD
        }
        else
        {
            settings.setInt("last_password", 0);
            settings.writeSettings(CONFIG_FILE_NAME);
        }
#endif
    }
    if (btnSaveAndReboot)
    {
        btnSaveAndReboot = false;
        saveSettings();
        ESP.restart();
    }
    if (btnDontSaveAndReboot)
    {
        btnDontSaveAndReboot = false;
        ESP.restart();
    }
    if (btnExit)
    {
        btnExit = false;
        appManager.goBack();
    }
    if (btnOTA)
    {
        btnOTA = false;
    }
    if (btnCali)
    {
        btnCali = false;
        hal.calibrateTouch();
    }
    if (btnAbout)
    {
        btnAbout = false;
    }
    vTaskDelay(100);
}

void AppSettings::destruct()
{
}

static AppSettings app;